// ==UserScript==
// @name           Shack New Comments Marker
// @namespace      http://www.apartment167.com/overload/greasemonkey
// @description    Marks which comments are new since your last refresh
// @include        http://shacknews.com/laryn.x?*
// @include        http://*.shacknews.com/laryn.x?*
// @include        http://*.shacknews.com/frame_laryn.x?*
// @include        http://shacknews.com/frame_laryn.x?*
// ==/UserScript==

/*
	Shack New Comments Marker
	Author: Greg Laabs "OverloadUT"
	(C)2008 Greg Laabs
	
	REVISIONS:

	2008-05-07
		- Initial Release
*/
if ((script_enabled('new_comments_marker') == "true")  && (location.href.indexOf('laryn.x') != -1)) 
{

	function getTime() { benchmarkTimer = new Date(); return benchmarkTimer.getTime(); }
	
	// TODO: Set back to 400 before release
	var MAX_NEW_POSTS = 400;
	
	
	var benchmarkTimer = null;
	var scriptStartTime = getTime();
	
	function xpath_single(query) 
	{
		return document.evaluate(query, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
	}
	
	function xpath_single_parent(query) 
	{
		return parent.document.evaluate(query, parent.document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
	}
	
	function xpath(query) 
	{
		return document.evaluate(query, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	}
	
	// Gets the last ID posted on the entire page.
	// Used to record what the last post was every time the page loads, so we know what is new on the next refresh.
	function getLastID() 
	{
		var firstroot = xpath_single('//div[contains(@class, "oneline0")]');
		var elem = firstroot.singleNodeValue;
		var id = elem.parentNode.id;
		return id.substr(5);
	}
	
	function getLastIDInThread(id) 
	{
		var firstroot = xpath_single_parent('//div[@id="'+id+'"]//div[contains(@class, "oneline0")]');
		var elem = firstroot.singleNodeValue;
		var id = elem.parentNode.id;
		return id.substr(5);
	}
	
	function getAllPosts() 
	{
		var a = xpath('//li[starts-with(@id, "item_")]')
		return a;
	}
	
	function getAllNewPosts(last_id) 
	{
		var a = xpath('//li[number(substring-after(@id, "item_"))>'+last_id+']')
		return a;
	}
	
	temptest = getAllNewPosts;
	
	function modifyPosts(last_id) 
	{
		elems = getAllNewPosts(last_id);
		
		new_posts = 0;
		new_myreplies = 0;
		var aborted = false;
		//for (var i = 0; i < elems.length; i++) {
		for (item = null, i = 0; item = elems.snapshotItem(i); i++) 
		{
			new_posts++;
			if(new_posts > MAX_NEW_POSTS) 
			{
				aborted = true;
				break;
			}
			
			var replytome = false;
			if(my_id != null && highlightRepliesToMe) 
			{
				var parentdiv = item.parentNode.parentNode;
				var parentclass = '';
				
				if(parentdiv.className != "root") 
				{
					if(parentdiv.className == "capcontainer") 
					{
						// parent is a root post
						parentclass = parentdiv.parentNode.childNodes[1].className;
					} else 
					{
						// parent is a reply
						parentclass = parentdiv.childNodes[1].className;
					}
					
					if(parentclass.substr(parentclass.length - my_id.length) == my_id) 
					{
						new_myreplies++;
						replytome = true;
					}
				}
			}
			
			if(replytome) 
			{
				if(item.className == 'last')
					item.className += ' newcommentmarker_newpostlast_tome';
				else if (item.className == '')
					item.className = 'newcommentmarker_newpost_tome';
			} 
			else 
			{
				if(item.className == 'last')
					item.className += ' newcommentmarker_newpostlast';
				else if(item.className == 'sel last')
					item.className += ' newcommentmarker_newrootpost';
				else if (item.className == '')
					item.className = 'newcommentmarker_newpost';
			}
				
			// This is a nasty little hack to be sure the veritical lines go all blue when there is long stream of new posts.
			if (item == item.parentNode.childNodes[1]) 
			{
				item.parentNode.className = 'newcommentmarker_newulnode';
			}
		}
		if(aborted)
			return false;
		else
			return true;
	}
	
	function getMyID() 
	{
		var id = GM_getValue("my_id", null);
		if(id == null) 
		{ 
			var elem = xpath_single('//a[contains(@class,"this_user")]/..');
			elem = elem.singleNodeValue;
			if(elem) 
			{
				id = elem.className.substr(elem.className.indexOf("olauthor_")+9);
				GM_setValue("my_id",id);
			} 
		}
		
		return id;
	}
	
	// START
	
	
	var new_posts = 0;
	var new_myreplies = 0;
	
	var my_id = getMyID();
	
	var highlightRepliesToMe = GM_getValue("highlightRepliesToMe", null);
	if(highlightRepliesToMe == null) 
	{
		highlightRepliesToMe = true;
		GM_setValue("highlightRepliesToMe", true);
	}
	
	if (location.pathname == '/laryn.x') 
	{
		var last_refresh = GM_getValue("last_refresh", null);
		if (last_refresh != null) 
		{
			var timer = getTime();
			var success = modifyPosts(last_refresh);
			
			//if (GM_log) { GM_log('modifyPosts:' + (getTime() - timer) + 'ms'); }

			// CSS MOVED TO SHACKSCRIPTS.CSS
			
			if(success) 
			{	
				var elem = xpath_single('//p[@class="postcount"]');
				elem = elem.singleNodeValue;
				elem.innerHTML += ' (<span class="newcommentmarker_bluetext">'+new_posts+'</span> new posts)';
			}
		}
		
		var newlastid = getLastID();
		if (last_refresh == null || parseInt(newlastid) > parseInt(last_refresh)) 
		{
			GM_setValue("last_refresh",newlastid);
		}
			
		if (GM_log) { GM_log('newcommentsmarker.js: ' + (getTime() - scriptStartTime) + 'ms ('+new_posts+' new posts processed)'); }
	} 
	else if (location.pathname == '/frame_laryn.x') 
	{
		// frame_laryn.x is used when LOADING posts in a thread (loads content, replaces iframe, etc.)
		if (typeof(shacknewcommentmarker_replace_whole_element_from_iframe) == 'undefined') 
		{
			shacknewcommentmarker_replace_whole_element_from_iframe = replace_whole_element_from_iframe;
			replace_whole_element_from_iframe = function(element_name) {
				var lastid;
				if(parent.threadwatcher_active && parent.threadwatcher_lastReadID){
					lastid = parent.threadwatcher_lastReadID;
				} else {
					lastid = getLastIDInThread(element_name);
				}
				var success = modifyPosts(lastid);
				
				/* TODO: Need a good place to put the display of how many new posts in a refreshed thread. The capnote idea doesn't work.
				if(count) {
					var elem = xpath_single('//div[@class="capcontainer"]');
					elem = elem.singleNodeValue;
					elem.innerHTML = '<p class="newcommentmarker_refreshnote"><strong>'+count+'</strong> new posts</p>' + elem.innerHTML;
				}
				*/
				
				// Call original function
				return shacknewcommentmarker_replace_whole_element_from_iframe(element_name);
			}
		}
		if (GM_log) { GM_log('newcommentsmarker.js: ' + (getTime() - scriptStartTime) + 'ms ('+new_posts+' new posts processed)'); }
	}

}